package com.zhaoyd.uaademo.config;

import com.zhaoyd.uaademo.config.security.*;
import com.zhaoyd.uaademo.config.security.handler.LoginFailHandler;
import com.zhaoyd.uaademo.config.security.handler.LoginSuccessHandler;
import com.zhaoyd.uaademo.config.security.handler.LogoutSuccessHandler;
import com.zhaoyd.uaademo.config.security.handler.MyAccessDeniedHandler;
import com.zhaoyd.uaademo.config.security.integration.IntegrationAuthenticationFilter;
import com.zhaoyd.uaademo.config.security.integration.IntegrationUserDetailService;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private IntegrationUserDetailService integrationUserDetailService;
    @Resource
    private IntegrationAuthenticationFilter integrationAuthenticationFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //登录处理url,与拦截器一致
        String loginUrl = IntegrationAuthenticationFilter.LOGIN_PATH;
        http
            .csrf().disable()//关闭自带的csrf验证，方便直接使用接口调用
            .userDetailsService(integrationUserDetailService)//自定义userDetailService
            .addFilterBefore(integrationAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)//自定义集成登录拦截器
            .formLogin()
                .loginProcessingUrl(loginUrl)
                .successHandler(new LoginSuccessHandler())//登录成功
                .failureHandler(new LoginFailHandler())//失败返回处理
            .and()
                .exceptionHandling()
                .accessDeniedHandler(new MyAccessDeniedHandler())//无权限处理403
                .authenticationEntryPoint(new MyAuthenticationEntryPoint())//认证失败处理401
            .and()
                .authorizeRequests() // 授权配置
                .antMatchers(HttpMethod.OPTIONS).permitAll()
                .antMatchers(
                        loginUrl,//登录url
                        "/code/image",// 图片验证码接口
                        "/mylogout"//自定义登出接口，允许匿名访问（登录失效用户登出情况）
                ).permitAll() // 无需认证的请求路径
                .antMatchers(HttpMethod.POST,"/login","login").permitAll()
                .anyRequest().authenticated()// 其他请求全部验证
            .and()
                .logout()
                .logoutUrl("/signout") // 退出登录的url
                .logoutSuccessHandler(new LogoutSuccessHandler()) // 退出成功处理
                .deleteCookies("JSESSIONID") // 删除名为'JSESSIONID'的cookie（cookie模式用）
                ;
    }

    /**
     * 自定义密码编码器
     * DelegatingPasswordEncoder 密码密文字符串前用加'{密码类型}',不同密码类型用不同的PasswordEncoder解析
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}
